#include <gtest/gtest.h>

#include "memdb/impl/simple/Data.h"

using namespace memdb::impl::simple;

const char * dbPath = ".";
const char * tableName  = "test_data";
TEST(DataTest, test){
  Data d(dbPath, tableName);
  ASSERT_EQ(std::error_code(), d.open());

  ASSERT_EQ(std::error_code(), d.close());

  ASSERT_EQ(std::error_code(), d.open());

  ASSERT_EQ(std::error_code(), d.close());

  ASSERT_EQ(std::error_code(), d.destroy());
}

TEST(DataTest, testModify){

  Data d(dbPath, tableName);

  const char * key = "key";
  const char * expect_value = "world";

  ASSERT_FALSE(d.exists(key));

  {
    auto && ec = d.insert(key, expect_value);
    ASSERT_EQ(std::error_code(), ec);
  }

  ASSERT_TRUE(d.exists(key));

  {
    std::string value;
    auto && ec = d.get(key, value); 
    ASSERT_EQ(std::error_code(), ec);
    ASSERT_EQ(expect_value, value);
    std::cout << value << std::endl;
  }


  {
    const char * expect_new_value = "world11111";
    auto && ec = d.update(key,expect_new_value);
    ASSERT_EQ(std::error_code(), ec);

    std::string value;
    ec = d.get(key, value);
    ASSERT_EQ(std::error_code(), ec);
    ASSERT_TRUE(value == expect_new_value);
  }

  {
    
    const char * expect_third_value = "world22222";
    auto && ec = d.replace(key, expect_third_value);
    ASSERT_EQ(std::error_code(), ec);
    ASSERT_TRUE(d.exists(key));
    
    const char * not_exists_key = "hello-no-exists";
    ec = d.replace(not_exists_key, expect_third_value);
    ASSERT_EQ(std::error_code(), ec);
    ASSERT_TRUE(d.exists(not_exists_key));
  }

  {
    auto && ec = d.remove(key);
    ASSERT_EQ(std::error_code(), ec);
  }

  ASSERT_EQ(std::error_code(), d.destroy());
}

TEST(DataTest, testIter){
  Data d(dbPath, tableName);

  ASSERT_EQ(std::error_code(), d.insert("1", "1222"));
  ASSERT_EQ(std::error_code(), d.insert("2", "2222"));
  ASSERT_EQ(std::error_code(), d.insert("3", "3222"));
  ASSERT_EQ(std::error_code(), d.insert("4", "4222"));
  ASSERT_EQ(std::error_code(), d.insert("5", "5222"));

  ASSERT_EQ(5ull, d.iterator()->count());

  d.iterator()->foreach([](auto & item){
    std::cout << "all: "  << item->first << "|" << item->second << std::endl;
  });
  d.iterator((size_t)0, (size_t)2)->foreach([](auto & item){
    std::cout << "limit 2 offset 0:"<< item->first << "|" << item->second << std::endl;
  });
  d.iterator("3", (size_t)0, (size_t)2)->foreach([](auto & item){
    std::cout << "key-3 limit 2 offset 0:"<< item->first << "|" << item->second << std::endl;
  });


  ASSERT_EQ(std::error_code(), d.destroy());
}
